# -*- coding: UTF-8 -*-
# @Time : 2021/12/23 0023 14:18
# @Author : lyw
# @Remark :
import logging
from typing import NoReturn, Dict

from mxsoftpy import DB
from mxsoftpy.exception import DBError

from index import mini_cache, _
from utils.classes.custom_exception import VerifyError


class IOTBaseDB(DB):
    file = 'Co_1'
    main_key = 'CRM'
    device_type = ""
    query_field = ["mxlabel", "mxdevicetype", "mxparent", "isdel"]
    group_by_key = "type"
    data_sort_key = "priority"

    def get_alert_data(self):
        ups_cache = mini_cache.get("AC_ALERT_DATA_CACHE")
        if ups_cache:
            logging.info("空调告警信息读取缓存")
            res_dict = ups_cache
        else:
            res_dict = {
                # "1.SD.318.SubMonitor.23662927": "接收流量百分比(当前值:inf) 超过故障阈值(80.000(%))"
            }
            try:

                monitor_table_data = self.table.open("MXSE", "AlertEventLog").record_by_time(days=100, count=0)
                for monitor_data in monitor_table_data:
                    res_dict[monitor_data["MonitorId"]] = monitor_data["Description"]
            except DBError as e:
                logging.error(e)
            mini_cache.set("AC_ALERT_DATA_CACHE", res_dict, 30)
            logging.info("空调告警信息设置缓存")
        return res_dict

    def query_table_data(self, code, count, **kwargs):
        """
        获取table 数据
        @param code:
        @param count:
        @param kwargs:
        @return:
        """
        try:
            monitor_table_list = self.table.open("MXSE", code).record_by_time(count=count, **kwargs)
            return monitor_table_list
        except DBError as e:
            logging.error(e)

    def get_sub_monitor(self, code, device_data) -> NoReturn:
        """
        或者一个子级信息基本方法

        @return:
        """
        pass

    def retrieve(self, code):
        """
        查询设备
        @param code:
        @return:
        """
        try:

            device_data = self.tree.open("MXSE", "1\\1.SD\\%s" % code, file="ccubase").items(self.query_field)

            device_data["code"] = code
            # if device_data.get("isdel", 1):
            #     raise VerifyError(_("查询设备错误 is_del"))
            self.get_sub_monitor(code, device_data)
        except DBError as e:
            logging.error(e)
            raise VerifyError(_("查询设备错误"))
        return device_data

    def query_device(self, name="", code=None):
        """
        查找设备
        @return:
        """
        res_dev_list = []
        try:
            total, dev_key_list = self.tree.open("MXSE", "1\\1.SD", file="ccubase").filter(
                mxdevicetype__like="*%s*" % self.device_type, isdel=0, mxlabel__like="*%s*" % name)
        except DBError as e:
            logging.error(e)
            raise VerifyError(_("查询错误"))
        if code is not None:

            try:
                total, mid_keys = self.tree.open(self.main_key, "sroom_iot_middle",
                                                 file=self.file).filter(sroom_code=code,
                                                                        device_type=self.device_type)
                mid_list = set()
                if mid_keys:
                    mid_data = self.tree.open(self.main_key, "sroom_iot_middle", file=self.file).sub_items(mid_keys)

                    for key, value in mid_data.items():
                        mid_list.add(value["iot_code"])
                dev_key_list = list(set(dev_key_list) & mid_list)
            except DBError as e:
                logging.error(e)
                raise VerifyError(_("查询错误"))

        try:
            for sd_key in dev_key_list:
                data_value = self.tree.open("MXSE", "1\\1.SD\\%s" % sd_key, file="ccubase").items(self.query_field)

                data_value["code"] = sd_key

                self.get_sub_monitor(sd_key, data_value)
                res_dev_list.append(data_value)
        except DBError as e:
            logging.error(e)
            raise VerifyError(_("查询错误"))
        return res_dev_list

    def query_middle_all(self, data_obj):
        """
        查找机柜中间表
        @param data_obj:
        @return:
        """
        param: dict = self.param_middle(data_obj)
        try:
            total, mid_keys = self.tree.open(self.main_key, "sroom_iot_middle", file=self.file).filter(**param)
            res_list = []
            for mid_key in mid_keys:
                mid_value = self.tree.open(self.main_key, "sroom_iot_middle\\%s" % mid_key, file=self.file).items()
                mid_value["code"] = mid_key
                self.process_middle(res_list, mid_value)
        except DBError as e:
            logging.error(e)
            raise VerifyError(_("查询中间表错误"))
        return res_list

    def param_middle(self, data_obj) -> dict:
        """
        基础查询 参数
        @param data_obj:
        @return:
        """
        return {"sroom_code": data_obj.sroom_code, "iot_code": data_obj.iot_code, "device_type": data_obj.device_type}

    @staticmethod
    def process_middle(res_list, mid_value):
        """
        处理中间表数据 默认方法
        @param res_list:
        @param mid_value:
        @return:
        """
        res_list.append(mid_value)

    def group_by(self, middle_data: list) -> dict:
        """
        数据根据字段分组
        @return:
        """
        res_dict = {}
        for data in middle_data:
            print("group_by")
            group_by_key = data[self.group_by_key]
            if isinstance(res_dict.get(group_by_key), list):
                res_dict[group_by_key].append(data)
            else:
                res_dict[group_by_key] = [data]
            self.get_device_info(data)
        self.data_sort(res_dict)
        return res_dict

    def data_sort(self, group_data: Dict[str, list]):
        """
        数据排序
        @return:
        """
        for data in group_data:
            group_data[data].sort(key=lambda x: x[self.data_sort_key], reverse=True)

    def get_device_info(self, data):
        """
        获取设备
        @param data:
        @return:
        """
        if data.get("device_type") != "janitor":
            data.update(self.retrieve(data["iot_code"]))
        else:
            pass

    def overview_model(self, res_dict: dict, sub_name1="conf_overview"):
        """
        递归获取概览模板
        @param res_dict:
        @param sub_name1:
        @return:
        """
        sub_key_list = self.tree.open(self.main_key, sub_name1, file=self.file).sub_keys()
        for sub_name2 in sub_key_list:
            sub_name = "\\".join([sub_name1, sub_name2])
            model_data = self.tree.open(self.main_key, sub_name, file=self.file).items()
            res_dict[sub_name] = model_data
            if model_data.get("type") is not None:
                continue
            else:
                res_dict[sub_name]["sub"] = {}
                self.overview_model(res_dict[sub_name]["sub"], sub_name)

    def get_overview(self):
        """
        获取模板并且缓存
        @return:
        """
        sroom_overview = mini_cache.get("SROOM_OVERVIEW")
        if not sroom_overview:
            overview_res_dict = {}
            self.overview_model(overview_res_dict)
            sroom_overview = mini_cache.set("SROOM_OVERVIEW", overview_res_dict, 60 * 60 * 24)
        return sroom_overview

    def get_room(self, code):
        """
        获取机房信息
        @param code:
        @return:
        """
        try:
            return self.tree.open(self.main_key, "crm_config\\server_room\\%s" % code, file=self.file).items(
                "parent_name")
        except DBError as e:
            logging.error(e)
            return {"parent_name": ""}

    def get_local(self, data_obj):
        """

        @param data_obj:
        @return:
        """
        middle_data = self.query_middle_all(data_obj)
        print("middle_data" * 10)
        print(data_obj)
        print(middle_data)
        print("middle_data" * 10)
        if middle_data:
            return self.get_room(middle_data[0]["sroom_code"])["parent_name"]
        return ""
